﻿using System;
using System.Linq;
using System.Reflection;
using Microsoft.Linq.Expressions;
using Microsoft.Scripting.Actions;
using Microsoft.Scripting.Actions.Calls;
using Microsoft.Scripting.Runtime;

namespace Cjc.ExpressionEngine.Excel.Runtime.Binding
{
	internal class ExcelCallAction : CallAction
	{
		public ExcelCallAction( string name, bool ignoreCase, params Argument[] arguments )
			: base( name, ignoreCase, arguments )
		{
		}

		public override MetaObject FallbackInvoke( MetaObject target, MetaObject[] args, MetaObject onBindingError )
		{
			throw new NotImplementedException();
		}

		public override MetaObject Fallback( MetaObject target, MetaObject[] args, MetaObject onBindingError )
		{
			var codeContext = target.Value as CodeContext;
			var context = codeContext.LanguageContext as ExcelContext;
			var binder = context.Binder as ExcelBinder;
			var scope = Expression.Constant( codeContext.Scope as ExcelScope );

			var paramBinder = new ParameterBinderWithCodeContext( context.Binder, target.Expression );

			var methodGroup = ReflectionCache.GetMethodGroup(
				typeof( ExcelHelpers ),
				base.Name,
				BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance | BindingFlags.IgnoreCase,
				( m, c ) => m.Name.Equals( base.Name, StringComparison.InvariantCultureIgnoreCase ) );

			if ( methodGroup == null )
			{
				return ExcelBinder.MakeError(
					binder.MakeMissingMemberError( typeof( ExcelHelpers ), base.Name ),
					Restrictions.Empty );
			}

			return binder.CallMethod(
				paramBinder,
				methodGroup.Methods.Select( t => t.Method ).Cast<MethodBase>().ToList(),
				args );
		}

		public override object HashCookie
		{
			get { return this; }
		}
	}
}